; Question 1

(define number->string
	(lambda (n) "NUM"))


(define scheme->ml
  (letrec 
      (
       ; Auxilary functions
       ; ------------------
       (number->ml
        (lambda (num)
          (if (>= num 0)
              (number->string num)
              (string-append "(~" (number->string (- 0 num)) ")"))))
       
       (lambda->ml
        (lambda (exp)
          (string-append "(fn (" (sequence->ml (cadr exp) ",") ") => " (sequence->ml (cddr exp) " ") ")")))
        
       (sequence->ml
        (lambda (seq delimiter)
          (cond
            ((null? seq) "")
            (else
             (if (null? (cdr seq))
                 (subsequence->ml (car seq))
                 (string-append (subsequence->ml (car seq)) delimiter (sequence->ml (cdr seq) delimiter)))))))
       
       (subsequence->ml
        (lambda (exp)
          (if (list? exp)
              (string-append "(" (scheme->ml exp) ")")
              (scheme->ml exp))))
       
       (if->ml
        (lambda (exp)
         (string-append "if " (scheme->ml (cadr exp)) 
                        " then " (scheme->ml (caddr exp)) 
                        " else " (scheme->ml (cadddr exp)))))
       
       (minus->ml
        (lambda (exp)
          (if (null? (cddr exp))
              (string-append "~(" (scheme->ml (cadr exp)) ")")
              (special->ml exp))))
       
       (special->ml
        (lambda (exp)
          (sequence->ml (cdr exp) (scheme->ml (car exp)))))
       
       (special-boolean->ml
        (lambda (lst mark)
          (if (null? (cddr lst))
              (string-append "(" (scheme->ml (car lst)) mark (scheme->ml (cadr lst)) ")")
              (string-append "(" (scheme->ml (car lst)) mark (scheme->ml (cadr lst)) 
                             ") andalso " (special-boolean->ml (cdr lst) mark)))))
       
       (application->ml
        (lambda (exp)
          (string-append "(" (scheme->ml (car exp)) "(" (sequence->ml (cdr exp) ",") "))")))
       
       )
    ; The Main Procedure
    ; ------------------
    (lambda (exp)
      (cond
        ((null? exp) "")
        ; atomic types
        ((number? exp) (number->ml exp))
        ((boolean? exp) (if exp "true" "false"))
        ((string? exp)  (string-append "\"" exp "\""))
        ((symbol? exp) (symbol->string exp))
        ; non-atomic types
        ((list? exp)
         (let
             ((kind (car exp))) ; gets the type of the expression
           (cond
             ((eq? kind 'lambda) (lambda->ml exp))
             ((eq? kind 'if) (if->ml exp))
             ((eq? kind '-) (minus->ml exp))
             ((or (eq? kind '+)
                  (eq? kind '*))
              (special->ml exp))
             ((or (eq? kind '<)
                  (eq? kind '<=)
                  (eq? kind '=)
                  (eq? kind '>=)
                  (eq? kind '>))
              (special-boolean->ml (cdr exp) (scheme->ml kind)))
             (else (application->ml exp)
                   ))))
         (else
          (error "Unknown expression type!" exp))))
      ))


(scheme->ml '((lambda (f g) (- (f 5) (g 6 6))) (lambda (n) (* n n)) (lambda (n m) (if (= n m) 5 (- 5 7)))))
